use crate::{config, data, guard, server, session};
use actix::*;
use actix_web::{web, Error, HttpRequest, HttpResponse};
use actix_web_actors::ws;
use serde::Serialize;
use std::time::Instant;

#[derive(Serialize)]
struct DisplayStatus {
    id: usize,
    leader: usize,
    role: String,
    status: String,
}

// #[derive(Debug)]
// struct ServerIDSameError {
//     name: &'static str,
// }

// Displays state
// /cgi/display/status
async fn cgi_display_status() -> web::Json<DisplayStatus> {
    if config::get_server_singleton() {
        web::Json(DisplayStatus {
            id: 0,
            leader: 0,
            role: format!("{:?}", data::Role::Singleton),
            status: format!("{:?}", data::Status::Leading),
        })
    } else {
        let role;
        let status;
        let id;
        let leader;
        {
            let &(ref lock, ref _cvar) = &*data::SHARE_GLOBAL_AREA_MUTEX_PAIR.clone();
            let loc = lock.lock();
            // Acquired Lock: ReadOnly
            id = loc.vcd.myid;
            leader = loc.vcd.leader;
            role = loc.role.clone();
            status = loc.status.clone();
            // Released Lock
        }

        web::Json(DisplayStatus {
            id,
            leader,
            role: format!("{:?}", role),
            status: format!("{:?}", status),
        })
    }
}

// ws://<path>/im/chat/123456?app_id=yyy&app_key=xxx
async fn chat_route(
    params: web::Path<(usize, usize)>,
    req: HttpRequest,
    stream: web::Payload,
    srv: web::Data<Addr<server::ChatServer>>,
) -> Result<HttpResponse, Error> {
    let ip = req.peer_addr().unwrap().ip();
    let server_id = params.0;
    let client_id = params.1;

    // if myid == client_id {
    //     let result = Err(ServerIDSameError { name: "A follower with the same server_id as this slave has connected to the leader or other follower" });
    //     return result.map_err(|err| actix_web::error::ErrorConflict(err.name));
    // }

    log::debug!("{} - Connection ready, endpoint: {}", ip, req.full_url());

    ws::start(
        session::WsChatSession {
            server_id,
            client_id,
            session_id: 0,
            hb: Instant::now(),
            addr: srv.get_ref().clone(),
            closed: false,
            // ip,
            id_rsa: ("".to_owned(), "".to_owned()),
        },
        &req,
        stream,
    )
}

pub fn config(cfg: &mut web::ServiceConfig) {
    // cfg.service(web::resource("/test")
    //     .route(web::get().to(|| HttpResponse::Ok()))
    //     .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
    // )

    // .service(Files::new("/static", "./static"))
    cfg.service(
        web::resource("/im/chat/{server_id}/{client_id}")
            // .guard(guard::im::ClusterModeGuard)
            .guard(guard::im::IMGuard)
            .to(chat_route),
    )
    // .default_service(
    //     web::route().guard(guard::im::ClusterModeGuard).to(HttpResponse::BadRequest),
    // )
    .default_service(
        web::route()
            .guard(guard::im::IMGuard)
            .to(HttpResponse::Unauthorized),
    )
    .service(web::scope("/cgi/display").service(web::resource("status").to(cgi_display_status)));
    // .service(web::resource("/openapi/status").to(get_status));
    // .route("/count", web::get().to(get_count));
}

// ogi = Open Gateway Interface
